# 序列化文件，定义序列化器
import datetime
import re

from django.contrib.auth.hashers import make_password, check_password
from django.core.cache import cache
from django.db.models import Q
from rest_framework import serializers
from cost.models import *

from cost.re_helper import *
from utils.errors import ParamsException


class UserSerializer(serializers.ModelSerializer):
    """
        实现序列化，序列化的字段由fields来定义
        实现字段校验，默认按照model中指定的Article模型中定义的字段规则来校验
    """

    # 这里可以自定义约束的校验条件
    username = serializers.CharField(min_length=4, max_length=16, required=True,
                                     error_messages={
                                         'required': '用户名必填',
                                         'min_length': '用户名长度最小为4',
                                         'max_length': '用户名长度最大为16',
                                     })
    password = serializers.CharField(min_length=6, max_length=16, required=True,
                                     error_messages={
                                         'required': '密码必填',
                                         'min_length': '密码长度最小为6',
                                         'max_length': '密码长度最大为16',
                                     })
    tel = serializers.CharField(min_length=11, max_length=11, required=True,
                                error_messages={
                                    'required': '手机号必填',
                                    'min_length': '手机号长度最小为11',
                                    'max_length': '手机号长度最大为11',
                                })

    class Meta:
        # 指定序列化的模型
        model = User
        # 指定序列化哪些字段，也限制前端传的数据必须有以下字段
        fields = ['username', 'password', 'tel', 'user_bir']

    # 这里决定返回给前端的数据
    def to_representation(self, instance):
        # 该方法就是进行序列化的方法
        # 实现功能： 对象 ====> dict
        data = super().to_representation(instance)
        data['user_id'] = instance.user_id
        del data['password']
        data['img_load'] = instance.user_img
        # 返回前端的数据一定是序列化后的结果，不可能返回对象给前端
        # account_set能从user对应的id取得对应的account
        account = instance.account_set.all()
        # data['account'] = AccountSerializer(account, many=True).data
        return data

    # 用于校验字段， attrs就是拿到前端传来的参数的值
    def validate(self, attrs):
        username = attrs.get('username')
        tel = attrs.get('tel')
        password = attrs.get('password')
        if not re.fullmatch(USERNAME_RE, username):
            res = {'code': '1001', 'message': '该用户名不符合命名规则，请重试', 'data': {'username': username, 'rule': '由汉字字母数字下滑线组成4-16位'}}
            raise ParamsException(res)
        if not re.fullmatch(PASSWORD, password):
            res = {'code': '1002', 'message': '该密码不符合密码规则，请重试', 'data': {'password': password, 'rule': '由字母数字英文.组成6-16位,并且以字母开头'}}
            raise ParamsException(res)
        if not re.fullmatch(TEL, tel):
            res = {'code': '1003', 'message': '该手机号不符合规则，请重试', 'data': {'tel': tel, 'rule': '该手机号不符合规则，请重试'}}
            raise ParamsException(res)
        if User.objects.filter(tel=tel).exists():
            res = {'code': '1004', 'message': '该手机号已存在，请核实是否为您的手机号，可找回密码', 'data': {'tel': tel, 'rule': tel}}
            raise ParamsException(res)
        else:
            return attrs


# 这个序列化器是为了将account中的user字段转为字典而专门创建的
class User2Serializer(serializers.ModelSerializer):
    class Meta:
        # 指定序列化的模型
        model = User
        # 指定序列化哪些字段，也限制前端传的数据必须有以下字段
        fields = ['user_id', 'username', 'tel']


# 银行卡信息序列化器
class AccountSerializer(serializers.ModelSerializer):

    account_name = serializers.CharField(max_length=64, required=True,
                                         error_messages={
                                             'max_length': '卡名称最长为64字节',
                                             'required': '卡名称必填'
                                         })
    account_num = serializers.CharField(max_length=16, min_length=16, required=True,
                                         error_messages={
                                             'max_length': '卡号最长为16',
                                             'min_length': '卡号最短为16',
                                             'required': '卡号必填'
                                         })
    account_amount = serializers.CharField(required=True, error_messages={'required': '账户余额必填'})
    # 这个地方应该有问题
    user_id = serializers.CharField(required=True, error_messages={'required': '用户token必填'})

    class Meta:
        model = Account
        fields = ['account_name', 'account_num', 'account_amount', 'user_id']

    def to_representation(self, instance):
        data = super().to_representation(instance)
        data['account_id'] = instance.account_id
        data['account_num'] = instance.account_num[:4] + '*'*8 + instance.account_num[-4:]
        # 将user显示的id值转为对应的user对象的属性
        data['user'] = User2Serializer(instance.user).data
        # data['detail'] = DetailSerializer(instance.details_set.all(), many=True).data
        del data['account_amount']
        return data

    def validate(self, attrs):
        account_name = attrs.get('account_name')
        account_num = attrs.get('account_num')
        account_amount = attrs.get('account_amount', '0.00')
        token = attrs.get('user_id')
        print(token)
        # 通过token找出来的id来添加银行卡
        user_id = int(cache.get(token))
        print(user_id)

        if not re.fullmatch(ACCOUNT_NAME, account_name):
            res = {'code': '2001', 'message': '该银行卡名不符合规范', 'data': {'account_name': account_name, 'rule': '格式应为两位中文及以上'}}
            raise ParamsException(res)
        if not re.fullmatch(r'^[0-9]+.?[0-9]*$', account_amount):
            res = {'code': '2002', 'message': '该银行卡余额不符合规范', 'data': {'account_amount': account_amount, 'rule': '格式应为数字,如120.10'}}
            raise ParamsException(res)
        if not re.fullmatch(ACCOUNT_NUM, account_num):
            res = {'code': '2003', 'message': '该银行卡号不符合规范', 'data': {'account_num': account_num, 'rule': '长度为16为数字'}}
            raise ParamsException(res)

        user = User.objects.filter(user_id=user_id).first()
        print(user.user_id, user.username)
        if user is None:
            res = {'code': '2005', 'message': '该用户不存在，无法添加银行卡', 'data': {'user': user_id, 'rule': '该用户不存在，无法添加银行卡'}}
            raise ParamsException(res)
        if user.user_status == 0:
            res = {'code': '2004', 'message': '用户状态为禁用，无法添加银行卡', 'data': {'user': user_id, 'rule': '用户状态为禁用，无法添加银行卡'}}
            raise ParamsException(res)
        if Account.objects.filter(account_num=account_num).exists():
            res = {'code': '2006', 'message': '该卡号已存在，无需重复添加', 'data': {'account_num': account_num[:4]+'*'*8 + account_num[-4:], 'rule': '该卡号已存在，无需重复添加'}}
            raise ParamsException(res)
        else:
            return attrs

    # 这个方法会在调用save()方法时被调用。
    def create(self, validated_data):
        account_name = validated_data.get('account_name')
        account_num = validated_data.get('account_num')
        account_amount = '%.2f' % float(validated_data.get('account_amount'))
        user_id = int(cache.get(validated_data.get('user_id')))
        account = Account.objects.create(account_name=account_name, account_num=account_num, account_amount=account_amount, user_id=user_id)
        return account


# 信息详情序列化器
class DetailSerializer(serializers.ModelSerializer):
    class Meta:
        model = Details
        fields = ['detail_type', 'detail_num', 'detail_info', 'account', 'detail_id', 'detail_time']

    def to_representation(self, instance):
        data = super().to_representation(instance)
        data['time'] = instance.detail_time
        # data['detail_type'] = '支出' if data['detail_type'] == 1 else '收入'
        data['account'] = Account2Serializer(instance.account).data
        return data

    # 这个方法会在调用save()方法时被调用。
    def create(self, validated_data):
        detail = Details()
        detail.detail_time = validated_data.get('detail_time')
        detail.detail_type = validated_data.get('detail_type')
        detail.detail_num = validated_data.get('detail_num')
        detail.detail_info = validated_data.get('detail_info', '暂无备注')
        detail.account = validated_data.get('account')
        detail.save()
        return detail


class Account2Serializer(serializers.ModelSerializer):
    class Meta:
        model = Account
        fields = '__all__'

    def to_representation(self, instance):
        data = super().to_representation(instance)
        del data['account_amount']
        data['account_num'] = data['account_num'][:4] + '*'*8 + data['account_num'][-4:]
        del data['account_status']
        del data['user']
        return data


# 通过用户直接取得消费详情序列化器
class UserDetailSerializer(serializers.ModelSerializer):
    class Meta:
        # 指定序列化的模型
        model = User
        # 指定序列化哪些字段，也限制前端传的数据必须有以下字段
        fields = ['user_id', 'username', 'tel']

    def to_representation(self, instance):
        data = super().to_representation(instance)
        account = instance.account_set.all()
        ids = [item.account_id for item in account]
        # 查出user_id对应的银行卡对应的account_id对应的消费记录
        detail = Details.objects.filter(account__in=ids).all()
        data['details'] = DetailSerializer(detail, many=True).data
        return data


# 银行卡消费记录序列化器
class AccountDetailSerializer(serializers.ModelSerializer):
    class Meta:
        model = Account
        fields = ['account_name', 'account_num', 'account_amount', 'user']

    def to_representation(self, instance):
        data = super().to_representation(instance)
        data['account_id'] = instance.account_id
        data['account_num'] = instance.account_num[:4] + '*'*8 + instance.account_num[-4:]
        # 将user显示的id值转为对应的user对象的属性
        data['user'] = User2Serializer(instance.user).data
        data['detail'] = DetailSerializer(instance.details_set.order_by('-detail_time').all(), many=True).data
        return data


# 用户注册字段校验
class UserRegisterSerializer(serializers.Serializer):
    # 继承Serializer，只实现字段检验功能
    username = serializers.CharField(min_length=4, max_length=16, required=True,
                                     error_messages={
                                         'required': '用户名必填',
                                         'min_length': '用户名长度最小为4',
                                         'max_length': '用户名长度最大为16',
                                     })
    password = serializers.CharField(min_length=6, max_length=16, required=True,
                                     error_messages={
                                         'required': '密码必填',
                                         'min_length': '密码长度最小为6',
                                         'max_length': '密码长度最大为16',
                                     })
    tel = serializers.CharField(min_length=11, max_length=11, required=True,
                                error_messages={
                                    'required': '手机号必填',
                                    'min_length': '手机号长度最小为11',
                                    'max_length': '手机号长度最大为11',
                                })

    # 自定义校验部分
    def validate(self, attrs):
        username = attrs.get('username')
        password = attrs.get('password')
        tel = attrs.get('tel')
        if not re.fullmatch(USERNAME_RE, username):
            res = {'code': '1001', 'message': '该用户名不符合命名规则，请重试', 'data': {'username': username, 'rule': '由汉字字母数字下滑线组成4-16位'}}
            raise ParamsException(res)
        if not re.fullmatch(PASSWORD, password):
            res = {'code': '1002', 'message': '该密码不符合密码规则，请重试', 'data': {'password': password, 'rule': '由字母数字英文.组成6-16位,并且以字母开头'}}
            raise ParamsException(res)
        if not re.fullmatch(TEL, tel):
            res = {'code': '1003', 'message': '该手机号不符合邮箱规则，请重试', 'data': {'email': tel, 'rule': '该手机号不符合邮箱规则，请重试'}}
            raise ParamsException(res)
        if User.objects.filter(tel=tel).exists():
            res = {'code': '1004', 'message': '该手机号已存在，请核实是否为您的手机号，可找回密码', 'data': {'tel': tel, 'rule': tel}}
            raise ParamsException(res)
        return attrs

    # 这个方法会在调用save()方法时被调用。
    def create(self, validated_data):
        username = validated_data.get('username')
        password = make_password(validated_data.get('password'))
        tel = validated_data.get('tel')
        user = User.objects.create(username=username, password=password, tel=tel)
        user_code = str(user.user_id).rjust(16, '8')
        # 检测是否卡号是否存在
        while True:
            account1 = Account.objects.filter(account_num=user_code).first()
            if account1:
                user_code = str(int(user_code)+1)
            else:
                break
        account = Account()
        account.account_name = '本地账户'
        account.account_num = user_code
        account.account_amount = 0.00
        account.user_id = user.user_id
        account.save()
        return user

    # 返回前端的字段
    def to_representation(self, instance):
        data = super().to_representation(instance)
        data['user_id'] = instance.user_id
        del data['password']
        return data


# 用户修改密码字段校验
class UpdatePasswordSerializer(serializers.Serializer):
    # 继承Serializer，只实现字段检验功能
    password = serializers.CharField(min_length=6, max_length=16, required=True,
                                     error_messages={
                                         'required': '密码必填',
                                         'min_length': '密码长度最小为6',
                                         'max_length': '密码长度最大为16',
                                     })
    password1 = serializers.CharField(min_length=6, max_length=16, required=True,
                                     error_messages={
                                         'required': '密码必填',
                                         'min_length': '密码长度最小为6',
                                         'max_length': '密码长度最大为16',
                                     })
    token = serializers.CharField(required=True, error_messages={'required': 'token必填'})

    # 自定义校验部分
    def validate(self, attrs):
        token = attrs.get('token')
        user_id = int(cache.get(token))
        if not user_id or not User.objects.get(pk=user_id):
            res = {'code': '1009', 'message': '错误请求，请重试', 'data': {'token': token}}
            raise ParamsException(res)
        password = attrs.get('password')
        password1 = attrs.get('password1')
        if not re.fullmatch(PASSWORD, password):
            res = {'code': '1002', 'message': '该密码不符合密码规则，请重试', 'data': {'password': password, 'rule': '由字母数字英文.组成6-16位,并且以字母开头'}}
            raise ParamsException(res)
        if not re.fullmatch(PASSWORD, password1):
            res = {'code': '1002', 'message': '该密码不符合密码规则，请重试', 'data': {'password': password, 'rule': '由字母数字英文.组成6-16位,并且以字母开头'}}
            raise ParamsException(res)
        print(make_password(password))
        print(User.objects.get(pk=user_id).password)
        if not check_password(password, User.objects.get(pk=user_id).password):
            res = {'code': '1010', 'message': '密码验证失败'}
            raise ParamsException(res)
        return attrs

    # 返回前端的字段
    def to_representation(self, instance):
        data = super().to_representation(instance)
        del data['password1']
        del data['password']
        del data['token']
        data['info'] = '成功'
        return data


# 用户修改昵称字段校验
class UpdateNameSerializer(serializers.Serializer):
    username = serializers.CharField(min_length=4, max_length=16, required=True,
                                     error_messages={
                                         'required': '用户名必填',
                                         'min_length': '用户名长度最小为4',
                                         'max_length': '用户名长度最大为16',
                                     })
    token = serializers.CharField(required=True, error_messages={'required': 'token必填'})

    # 自定义校验部分
    def validate(self, attrs):
        token = attrs.get('token')
        user_id = int(cache.get(token))
        if not user_id or not User.objects.get(pk=user_id):
            res = {'code': '1009', 'message': '错误请求，请重试', 'data': {'token': token}}
            raise ParamsException(res)
        username = attrs.get('username')
        if not re.fullmatch(USERNAME_RE, username):
            res = {'code': '1001', 'message': '该用户名不符合命名规则，请重试',
                   'data': {'username': username, 'rule': '由汉字字母数字下滑线组成4-16位'}}
            raise ParamsException(res)
        return attrs

    # 返回前端的字段
    def to_representation(self, instance):
        data = super().to_representation(instance)
        del data['token']
        data['info'] = '成功'
        return data


# 用户修改昵称字段校验
class UpdateTelSerializer(serializers.Serializer):
    tel = serializers.CharField(min_length=11, max_length=11, required=True,
                                error_messages={
                                    'required': '手机号必填',
                                    'min_length': '手机号长度最小为11',
                                    'max_length': '手机号长度最大为11',
                                })
    token = serializers.CharField(required=True, error_messages={'required': 'token必填'})

    # 自定义校验部分
    def validate(self, attrs):
        token = attrs.get('token')
        user_id = int(cache.get(token))
        if not user_id or not User.objects.get(pk=user_id):
            res = {'code': '1009', 'message': '错误请求，请重试', 'data': {'token': token}}
            raise ParamsException(res)
        tel = attrs.get('tel')
        if not re.fullmatch(TEL, tel):
            res = {'code': '1003', 'message': '该手机号不符合规则，请重试', 'data': {'email': tel, 'rule': '该手机号不符合规则，请重试'}}
            raise ParamsException(res)
        if User.objects.filter(tel=tel).exists():
            res = {'code': '1004', 'message': '该手机号已存在，请核实是否为您的手机号，可找回密码', 'data': {'tel': tel, 'rule': tel}}
            raise ParamsException(res)
        return attrs

    # 返回前端的字段
    def to_representation(self, instance):
        data = super().to_representation(instance)
        del data['token']
        data['info'] = '成功'
        return data


# 用户注册字段校验
class UserLoginSerializer(serializers.Serializer):
    # 继承Serializer，只实现字段检验功能
    tel = serializers.CharField(min_length=11, max_length=11, required=True,
                                  error_messages={
                                      'required': '手机号必填',
                                      'min_length': '手机号长度最小为11',
                                      'max_length': '手机号长度最大为11',
                                  })
    password = serializers.CharField(min_length=6, max_length=16, required=True,
                                     error_messages={
                                         'required': '密码必填',
                                         'min_length': '密码长度最小为6',
                                         'max_length': '密码长度最大为16',
                                     })

    def validate(self, attrs):
        password = attrs.get('password')
        tel = attrs.get('tel')

        if not re.fullmatch(TEL, tel):
            res = {'code': '1003', 'message': '该手机号不符合规则，请重试', 'data': {'email': tel, 'rule': '该手机号不符合规则，请重试'}}
            raise ParamsException(res)
        if not User.objects.filter(tel=tel).exists():
            res = {'code': '1005', 'message': '该手机号尚未注册', 'data': {'tel': tel, 'rule': tel}}
            raise ParamsException(res)
        if not re.fullmatch(PASSWORD, password):
            res = {'code': '1002', 'message': '输入密码不合法，请重试', 'data': {'password': password, 'rule': '由字母数字英文.组成6-16位,并且以字母开头'}}
            raise ParamsException(res)
        if not check_password(password, User.objects.filter(tel=tel).first().password):
            res = {'code': '1010', 'message': '输入手机号或密码错误，请重试', 'data': {'rule':'输入手机号或密码错误，请重试'}}
            raise ParamsException(res)
        return attrs


# 修改银行卡字段校验
class ChangeAccountSerializer(serializers.Serializer):

    account_name = serializers.CharField(max_length=64, required=True,
                                         error_messages={
                                             'max_length': '卡名称最长为64字节',
                                             'required': '卡名称必填'
                                         })
    account_num = serializers.CharField(max_length=16, min_length=16, required=True,
                                         error_messages={
                                             'max_length': '卡号最长为16',
                                             'min_length': '卡号最短为16',
                                             'required': '卡号必填'
                                         })
    account_amount = serializers.CharField(required=True, error_messages={'required': '账户余额必填'})
    # 这个地方应该有问题
    account_id = serializers.CharField(required=True, error_messages={'required': '卡id必填'})

    token = serializers.CharField(required=True, error_messages={'required': '用户token必填'})

    def validate(self, attrs):
        account_name = attrs.get('account_name')
        account_num = attrs.get('account_num')
        account_amount = attrs.get('account_amount', '0.00')
        token = attrs.get('token')
        account_id = attrs.get('account_id')
        print(token)
        # 通过token找出来的id来添加银行卡
        user_id = int(cache.get(token))

        try:
            account = Account.objects.get(pk=account_id)
            if account.user.user_id != user_id:
                res = {'code': '2008', 'message': '未知错误', 'data': {}}
                raise ParamsException(res)
        except:
            res = {'code': '2007', 'message': '未知错误', 'data': {}}
            raise ParamsException(res)

        if not re.fullmatch(ACCOUNT_NAME, account_name):
            res = {'code': '2001', 'message': '该银行卡名不符合规范', 'data': {'account_name': account_name, 'rule': '格式应为两位中文及以上'}}
            raise ParamsException(res)
        if not re.fullmatch(r'^[0-9]+.?[0-9]*$', account_amount):
            res = {'code': '2002', 'message': '该银行卡余额不符合规范', 'data': {'account_amount': account_amount, 'rule': '格式应为数字,如120.10'}}
            raise ParamsException(res)
        if not re.fullmatch(ACCOUNT_NUM, account_num):
            res = {'code': '2003', 'message': '该银行卡号不符合规范', 'data': {'account_num': account_num, 'rule': '长度为16为数字'}}
            raise ParamsException(res)

        user = User.objects.filter(user_id=user_id).first()
        print(user.user_id, user.username)
        if user is None:
            res = {'code': '2005', 'message': '该用户不存在，无法添加银行卡', 'data': {'user': user_id, 'rule': '该用户不存在，无法添加银行卡'}}
            raise ParamsException(res)
        if user.user_status == 0:
            res = {'code': '2004', 'message': '用户状态为禁用，无法添加银行卡', 'data': {'user': user_id, 'rule': '用户状态为禁用，无法添加银行卡'}}
            raise ParamsException(res)
        if Account.objects.filter(account_num=account_num).exists() and Account.objects.filter(account_num=account_num).first().user.user_id != user_id:
            res = {'code': '2006', 'message': '该卡号已存在', 'data': {'account_num': account_num[:4]+'*'*8 + account_num[-4:], 'rule': '该卡号已存在'}}
            raise ParamsException(res)
        else:
            return attrs


# 修改信息字段校验
class ChangeDetailSerializer(serializers.Serializer):

    detail_info = serializers.CharField(max_length=1024, required=False, error_messages={'max_length': '备注最长为1024字节',})
    detail_time = serializers.CharField(required=True, error_messages={'required': '时间必填'})
    detail_type = serializers.CharField(required=True, error_messages={'required': '类型必填'})

    detail_num = serializers.CharField(required=True, error_messages={'required': '金额必填'})
    # 这个地方应该有问题
    detail_id = serializers.CharField(required=True, error_messages={'required': '信息id必填'})

    token = serializers.CharField(required=True, error_messages={'required': '用户token必填'})

    def validate(self, attrs):
        detail_info = attrs.get('detail_info', '空')
        detail_time = attrs.get('detail_time')
        detail_type = attrs.get('detail_type')
        detail_num = attrs.get('detail_num')
        detail_id = attrs.get('detail_id')
        token = attrs.get('token')
        # 通过token找出来的id来添加银行卡
        user_id = int(cache.get(token))
        # 判断时间
        test_time = detail_time.split('T')[1]
        if not re.fullmatch(r'^((0[0-9])|(1[0-9])|(2[0-3])):([0-5][0-9]):([0-5][0-9])\.11$', test_time):
            res = {'code': '3003', 'message': '消费时间不被允许 格式请参照原有格式', 'data': {'rule': '消费时间不被允许 格式请参照原有格式'}}
            raise ParamsException(res)
        # print(int(detail_time.split('-')[0].lstrip('0')))
        # print(int(detail_time.split('-')[1].lstrip('0')))
        if (2024 >= int(detail_time.split('-')[0].lstrip('0')) >= 2019) and (12 >= int(detail_time.split('-')[1].lstrip('0')) >= 1):
            pass
        else:
            res = {'code': '3011', 'message': '修改失败 年份在2019-2024 月份在1-12', 'data': {}}
            raise ParamsException(res)

        try:
            details = Details.objects.get(pk=detail_id)
            if details.account.user.user_id != user_id:
                res = {'code': '2008', 'message': '未知错误', 'data': {}}
                raise ParamsException(res)
        except:
            res = {'code': '2007', 'message': '未知错误', 'data': {}}
            raise ParamsException(res)

        try:
            a = float(detail_num)
        except:
            res = {'code': '2008', 'message': '金额不是数字', 'data': {}}
            raise ParamsException(res)

        if detail_type not in ['收入', '借出', '餐饮', '通讯', '娱乐', '购物', '交通', '杂项']:
            res = {'code': '3002', 'message': '消费类型不被允许', 'data': {'rule': '消费类型不被允许'}}
            raise ParamsException(res)
        else:
            return attrs

    # 这个方法会在调用save()方法时被调用。
    def create(self, validated_data):
        detail_id = validated_data.get('detail_id')
        detail_num = validated_data.get('detail_num')
        detail_time = validated_data.get('detail_time')
        detail_info = validated_data.get('detail_info', '暂无备注')
        detail_type = validated_data.get('detail_type')
        token = validated_data.get('token')
        detail = Details.objects.get(pk=detail_id)
        account = detail.account
        # 寻找原有local记录
        old_time_year = detail.detail_time.year
        old_time_month = detail.detail_time.month

        # 修改原有记录
        locals = Locals.objects.filter(Q(user_id=cache.get(token)) & Q(local_year=old_time_year) & Q(local_month=old_time_month)).first()
        try:
            # 修改关联卡信息
            account_amount = float(account.account_amount)
            old_type = detail.detail_type
            old_num = detail.detail_num
            if old_type == '收入':
                account_amount = account_amount - float(old_num)
            else:
                account_amount = account_amount + float(old_num)
            if detail_type == '收入':
                account_amount = account_amount + float(detail_num)
            else:
                account_amount = account_amount - float(detail_num)
            account.account_amount = account_amount

            # 清除原有数据
            local_amount = float(locals.local_amount)
            local_in = float(locals.local_in)
            local_out = float(locals.local_out)
            local_income = float(locals.local_income)
            local_jie = float(locals.local_jie)
            local_food = float(locals.local_food)
            local_phone = float(locals.local_phone)
            local_game = float(locals.local_game)
            local_shop = float(locals.local_shop)
            local_traffic = float(locals.local_traffic)
            local_other = float(locals.local_other)

            if old_type == '收入':
                local_amount = local_amount - float(old_num)
                local_income = local_income - float(old_num)
                local_in = local_in - float(old_num)
            elif old_type == '借出':
                local_amount = local_amount + float(old_num)
                local_jie = local_jie - float(old_num)
                local_out = local_out - float(old_num)
            elif old_type == '餐饮':
                local_amount = local_amount + float(old_num)
                local_food = local_food - float(old_num)
                local_out = local_out - float(old_num)
            elif old_type == '通讯':
                local_amount = local_amount + float(old_num)
                local_phone = local_phone - float(old_num)
                local_out = local_out - float(old_num)
            elif old_type == '娱乐':
                local_amount = local_amount + float(old_num)
                local_game = local_game - float(old_num)
                local_out = local_out - float(old_num)
            elif old_type == '购物':
                local_amount = local_amount + float(old_num)
                local_shop = local_shop - float(old_num)
                local_out = local_out - float(old_num)
            elif old_type == '交通':
                local_amount = local_amount + float(old_num)
                local_traffic = local_traffic - float(old_num)
                local_out = local_out - float(old_num)
            elif old_type == '杂项':
                local_amount = local_amount + float(old_num)
                local_other = local_other - float(old_num)
                local_out = local_out - float(old_num)
            # 保存老旧local数据
            # 保存信息
            locals.local_amount = local_amount
            locals.local_in = local_in
            locals.local_out = local_out
            locals.local_income = local_income
            locals.local_jie = local_jie
            locals.local_game = local_game
            locals.local_traffic = local_traffic
            locals.local_phone = local_phone
            locals.local_food = local_food
            locals.local_shop = local_shop
            locals.local_other = local_other
            locals.save()
            # 添加现有local数据
            locals = Locals.objects.filter(
                Q(user_id=cache.get(token)) & Q(local_year=detail_time.split('-')[0].lstrip('0')) & Q(local_month=detail_time.split('-')[1].lstrip('0'))).first()
            if not locals and (2024 >= int(detail_time.split('-')[0].lstrip('0')) >= 2019) and (12 >= int(detail_time.split('-')[1].lstrip('0')) >= 1) :
                locals = Locals()
                locals.local_year = detail_time.split('-')[0].lstrip('0')
                locals.local_month = detail_time.split('-')[1].lstrip('0')
                locals.user_id = cache.get(token)
                locals.save()
            elif not locals and not((2024 >= int(detail_time.split('-')[0].lstrip('0')) >= 2019)) or not(12 >= int(detail_time.split('-')[1].lstrip('0')) >= 1):
                res = {'code': '3010', 'message': '错误请求,年份大于2020，小于2024', 'data': {'rule': '错误请求'}}
                raise ParamsException(res)
            if detail_type == '收入':
                locals.local_amount = float(locals.local_amount) + float(detail_num)
                locals.local_income = float(locals.local_income) + float(detail_num)
                locals.local_in = float(locals.local_in) + float(detail_num)
            elif detail_type == '借出':
                locals.local_amount = float(locals.local_amount) - float(detail_num)
                locals.local_jie = float(locals.local_jie) + float(detail_num)
                locals.local_out = float(locals.local_out) + float(detail_num)
            elif detail_type == '餐饮':
                locals.local_amount = float(locals.local_amount) - float(detail_num)
                locals.local_food = float(locals.local_food) + float(detail_num)
                locals.local_out = float(locals.local_out) + float(detail_num)
            elif detail_type == '通讯':
                locals.local_amount = float(locals.local_amount) - float(detail_num)
                locals.local_phone = float(locals.local_phone) + float(detail_num)
                locals.local_out = float(locals.local_out) + float(detail_num)
            elif detail_type == '娱乐':
                locals.local_amount = float(locals.local_amount) - float(detail_num)
                locals.local_game = float(locals.local_game) + float(detail_num)
                locals.local_out = float(locals.local_out) + float(detail_num)
            elif detail_type == '购物':
                locals.local_amount = float(locals.local_amount) - float(detail_num)
                locals.local_shop = float(locals.local_shop) + float(detail_num)
                locals.local_out = float(locals.local_out) + float(detail_num)
            elif detail_type == '交通':
                locals.local_amount = float(locals.local_amount) - float(detail_num)
                locals.local_traffic = float(locals.local_traffic) + float(detail_num)
                locals.local_out = float(locals.local_out) + float(detail_num)
            elif detail_type == '杂项':
                locals.local_amount = float(locals.local_amount) - float(detail_num)
                locals.local_other = float(locals.local_other) + float(detail_num)
                locals.local_out = float(locals.local_out) + float(detail_num)

            # 修改信息
            detail.detail_num = detail_num
            detail.detail_type = detail_type
            detail.detail_time = detail_time
            detail.detail_info = detail_info
            detail.save()
        except:
            res = {'code': '5001', 'message': '修改失败', 'data': {'rule': '修改失败'}}
            raise ParamsException(res)
        # 对应的对象
        locals.save()

        account.save()
        return detail
